/**
 * 
 */
package com.imonsoft.common.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.core.CollectionFactory;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

/**
 * 
 * @author LiQianHui
 * @date 2013-04-17
 * @version 2013
 */
abstract public class ReflectionUtil extends ReflectionUtils {

	/**
	 * 
	 * @param field
	 * @return
	 */
	public static boolean isFinalField(final Field field) {
		int modifiers = field.getModifiers();
		if (Modifier.isFinal(modifiers)) {
			return true;
		}
		return false;
	}

	/**
	 * 
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
	public static Map<String, Field> getWritableFields(final Class<?> clazz) {
		Assert.notNull(clazz, "clazz不能为空");

		Field[] fields = clazz.getDeclaredFields();
		Map<String, Field> map = CollectionFactory
				.createLinkedCaseInsensitiveMapIfPossible(fields.length);
		for (Field field : fields) {
			if (isFinalField(field)) {
				continue;
			}
			map.put(field.getName(), field);
			makeAccessible(field);
		}
		return map;
	}

	/**
	 * 
	 * @param fieldMap
	 *            bean的类的所有可set的Field
	 * @param object
	 * @param fieldName
	 *            oracle规则(AB_CD)或JavaBean规则名称(abCd)
	 * @param value
	 */
	public static void setFieldValue(Map<String, Field> fieldMap, final Object object,
			final String fieldName, final Object value) {
		Assert.notNull(fieldMap, "fieldMap不能为空");

		try {
			Field field = fieldMap.get(fieldName);
			if (field == null) {
				String fn = oracleColumn2JavaField(fieldName);
				field = fieldMap.get(fn);
				if (field == null) {
					return;
				}
			}
			field.set(object, value);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 
	 * @param str
	 * @return
	 */
	public static String oracleColumn2JavaField(String str) {
		if (str != null) {
			String[] strs = str.split("_");
			String toStr = strs[0].toLowerCase();
			for (int i = 1; i < strs.length; i++) {
				toStr += strs[i].substring(0, 1).toUpperCase() + strs[i].substring(1).toLowerCase();
			}
			return toStr;
		}
		return null;
	}

	/**
	 * 
	 * @param str
	 * @return
	 */
	public static String javaField2OracleColumn(String str) {
		if (str != null) {
			String toStr = "";
			char[] chars = str.toCharArray();
			for (int i = 0; i < chars.length; i++) {
				if (Character.isUpperCase(chars[i])) {
					toStr += "_";
				}
				toStr += String.valueOf(chars[i]).toUpperCase();
			}
			return toStr;
		}
		return null;
	}
	public static <T> T map2bean(Map<String, Object> map, Class<T> beanClass) {
		if (map == null) {
			return null;
		}
		T bean = null;
		try {
			Map<String, Field> fieldMap = ReflectionUtil.getWritableFields(beanClass);
			bean = beanClass.newInstance();
			Iterator<String> iterator = map.keySet().iterator();
			while (iterator.hasNext()) {
				String key = iterator.next();
				Object obj = map.get(key);
				String str = StringUtil.fixup(obj);
				ReflectionUtil.setFieldValue(fieldMap, bean, key, str);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return bean;
	}

	public static <T> List<T> list2beans(List<Map<String, Object>> list, Class<T> beanClass) {
		if (list == null) {
			return null;
		}
		List<T> beans = null;
		try {
			beans = new ArrayList<T>(list.size());
			Map<String, Field> fieldMap = ReflectionUtil.getWritableFields(beanClass);
			for (Map<String, Object> map : list) {
				T bean = beanClass.newInstance();
				Iterator<String> iterator = map.keySet().iterator();
				while (iterator.hasNext()) {
					String key = iterator.next();
					Object obj = map.get(key);
					String str =StringUtil.fixup(obj);
					ReflectionUtil.setFieldValue(fieldMap, bean, key, str);
				}
				beans.add(bean);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return beans;
	}

}
